package com.winning.pmph.ctrl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.winning.pmph.entity.*;
import com.winning.pmph.mapper.*;
import com.winning.pmph.service.TermService;
import com.winning.pmph.utils.*;
import com.winning.pmph.vo.TermBetweenVo;
import com.winning.pmph.vo.TermStandardVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 刘亚飞
 * @Description
 * @create 2021-03-30 14:37
 */
@Api(value = "知识库管理/术语库")
@Slf4j
@RestController
@RequestMapping("/pmph/action/term")
public class TermCtrl {

    @Resource
    private TermService termService;
    @Resource
    private TermBetweenMapper termBetweenMapper;
    @Resource
    private TermBookMetadataMapper termBookMetadataMapper;
    @Resource
    private TermStandardMapper termStandardMapper;
    @Resource
    private TermStandardHistoryMapper termStandardHistoryMapper;
    @Resource
    private TermStandardLibHistoryMapper termStandardLibHistoryMapper;
    @Resource
    private TermStandardLibHistoryItemMapper termStandardLibHistoryItemMapper;

    /**
     * 术语图书上传
     */
    @ApiOperation(value = "importBook", notes = "术语导入接口")
    @PostMapping("importBook")
    public String importBook(MultipartFile file, String bookMetadataId, HttpServletRequest request) {
        String header = request.getHeader("user-agent");

        String path = ApplicationContextUtil.BASE_DOWN_FORDER + "image/term/";
        try {
            String name = UploadFileUtil.uploadFile(file, path, false);
            // 文件上传成功后,开始解析,另起线程解析zip包
            // 向term_book_metadata表插入数据
            TermBookMetadata termBookMetadata = new TermBookMetadata();
            if (StringUtils.isNotBlank(bookMetadataId)) {
                termBookMetadata.setId(bookMetadataId);
            }
            termBookMetadata.setName(StringUtils.removeEnd(name, ".zip"));
            termBookMetadata.setFilePath(path + name);
            termBookMetadata.setUnZipPath(path + name);
            termBookMetadata.setStatus(TermBookMetadata.STATUS_IMPORTING);
            termBookMetadata.setDeleted(TermBookMetadata.DELETED_NO);
            termBookMetadata.setCreatedBy(PMPHAppUtil.getCurrentUserEnName());
            termBookMetadata.setCreatedTime(LocalDateTimeUtil.getNowAsString());
            termBookMetadata.setUpdatedBy(PMPHAppUtil.getCurrentUserEnName());
            termBookMetadata.setUpdatedTime(LocalDateTimeUtil.getNowAsString());
            termBookMetadataMapper.saveBean(termBookMetadata);
            // 另起线程解析zip包
            ExecutorServiceFactory.getInstance().submit(() -> {
                try {
                    //开始解压图书
                    termService.importBook(termBookMetadata, header);
                } catch (Exception e) {
                    termBookMetadata.setStatus(TermBookMetadata.STATUS_IMPORT_FAILURE);
                    termBookMetadata.setFailureReason(e.getMessage());
                    log.error("图书: " + termBookMetadata.getName() + ",上传失败: ", e);
                } finally {
                    termBookMetadataMapper.saveBean(termBookMetadata);
                    // 删除解压后的文件
                    try {
                        FileUtils.deleteDirectory(new File(StringUtils.removeEnd(termBookMetadata.getUnZipPath(), ".zip")));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // 导入成功后删除上传的zip包文件;
                    if (TermBookMetadata.STATUS_NO_SELFCHECKING.equals(termBookMetadata.getStatus())) {
                        FileUtils.deleteQuietly(new File(termBookMetadata.getUnZipPath()));
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("导入任务提交失败, 失败原因: " + e.getMessage());

        }
       return "导入任务提交成功, 请耐心等待";
    }

    @ApiOperation(value = "selectBookMetadata", notes = "查询图书元数据")
    @PostMapping("selectBookMetadata")
    public Map<String, Object> selectBookMetadata(String termBookMetadata) {
        Map<String, Object> map = Maps.newHashMap();
        TermBookMetadata termMetadata = JSONObject.toJavaObject(JSON.parseObject(termBookMetadata), TermBookMetadata.class);
        List<TermBookMetadata> list = termService.queryBookMetadata(termMetadata);
        int totalNum = termService.queryBookMetadataCount(termMetadata);
        map.put("totalNum", totalNum);
        map.put("tableData", list);
        boolean isfinish = true;
        if (CollectionUtils.isNotEmpty(list)) {
            if (CollectionUtils.isNotEmpty(list.stream().filter(t -> (4 == t.getStatus() || 5 == t.getStatus() || 7 == t.getStatus())).collect(Collectors.toList()))) {
                isfinish = false;
            }
        }
        map.put("isfinish", isfinish);
        return map;
    }

    @ApiOperation(value = "compareToStandard", notes = "正与标准术语库做对比接口")
    @GetMapping("compareToStandard")
    public String compareToStandard(String id) {
        String userCode = PMPHAppUtil.getCurrentUserEnName();
        try {
            TermBookMetadata termBookMetadata = termBookMetadataMapper.selectById(id);
            termBookMetadata.setStatus(TermBookMetadata.STATUS_COMPARING_STANDARD);
            termBookMetadata.setUpdatedBy(userCode);
            termBookMetadata.setUpdatedTime(LocalDateTimeUtil.getNowAsString());
            termBookMetadata.setStandardCheckBy(termBookMetadata.getUpdatedBy());
            termBookMetadata.setStandardCheckTime(termBookMetadata.getUpdatedTime());
            termBookMetadataMapper.saveBean(termBookMetadata);
            ExecutorServiceFactory.getInstance().submit(() -> {
                try {
                    //开始对比
                    termService.compareToStandard(termBookMetadata);
                } catch (Exception e) {
                    termBookMetadata.setStatus(TermBookMetadata.STATUS_ERROR_STANDARD);
                    termBookMetadata.setFailureReason(e.toString());
                    log.error("图书对比出错,错误原因:{}", e);
                } finally {
                    termBookMetadataMapper.saveBean(termBookMetadata);
                }
            });
        } catch (Exception e) {
            throw new RuntimeException("提交对比任务失败:" + e.toString());
        }
        return "正与标准术语库做对比, 请耐心等待";
    }

    @ApiOperation(value = "selectStandardList", notes = "查询术语正式库列表接口")
    @GetMapping("selectStandardList")
    public Map<String, Object> selectStandardList(Integer currentPage, Integer pageSize, String name) {
        Map<String, Object> map = Maps.newHashMap();
        TermStandard termStandard = new TermStandard();

        termStandard.setName(name);
        Page<TermStandard> page = termService.queryStandardList(termStandard, currentPage, pageSize);
        map.put("totalNum", page.getTotal());
        map.put("tableData", page.getRecords());
        return map;
    }

    @ApiOperation(value = "selectTermList", notes = "查询原始术语列表接口")
    @PostMapping("selectTermList")
    public TermBookMetadata selectTermList(String term) {
        Term terms = JSONObject.toJavaObject(JSON.parseObject(term), Term.class);
        TermBookMetadata termBookMetadata = termService.queryTermList(terms);
        return termBookMetadata;
    }

    @ApiOperation(value = "selectDetailTermById", notes = "根据id查看原始术语详情")
    @GetMapping("selectDetailTermById")
    public Term selectDetailTermById(String originalConceptId) {
        return termService.detailTermById(originalConceptId);
    }

    @ApiOperation(value = "selectDetailStandardById", notes = "根据id查看标准术语详情")
    @GetMapping("selectDetailStandardById")
    public TermStandard selectDetailStandardById(String id) {
        return termStandardMapper.selectById(id);
    }

    @ApiOperation(value = "updateMetadataById", notes = "根据id修改元数据接口")
    @PostMapping("updateMetadataById")
    public void updateMetadataById(String data, String id) {
        JSONObject metadataJson = JSONObject.parseObject(data);
        TermBookMetadata termBookMetadata = new TermBookMetadata();
        termBookMetadata.setId(id);
        String name = (String) ((JSONObject) metadataJson.get("Titles")).get("Main_Title");
        termBookMetadata.setMetadata(data);
        termBookMetadata.setName(name);
        termBookMetadata.setCategory(metadataJson.getInteger("Category"));
        try {
            termService.updateMetadataById(termBookMetadata);
        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    @ApiOperation(value = "selfChecking", notes = "图书自检接口")
    @GetMapping("selfChecking")
    public String selfChecking(String id) {

        String userCode = PMPHAppUtil.getCurrentUserEnName();
        try {
            TermBookMetadata termBookMetadata = termBookMetadataMapper.selectById(id);
            termBookMetadata.setStatus(TermBookMetadata.STATUS_COMPARING);
            termBookMetadata.setUpdatedBy(userCode);
            termBookMetadata.setUpdatedTime(LocalDateTimeUtil.getNowAsString());
            termBookMetadata.setSelfCheckBy(userCode);
            termBookMetadata.setSelfCheckTime(LocalDateTimeUtil.getNowAsString());
            termBookMetadataMapper.saveBean(termBookMetadata);
            ExecutorServiceFactory.getInstance().submit(() -> {
                try {
                    //开始自检
                    termService.selfChecking(termBookMetadata);
                } catch (Exception e) {
                    termBookMetadata.setStatus(TermBookMetadata.STATUS_COMPARE_ERROR);
                    termBookMetadata.setFailureReason(e.toString());
                    log.error("图书自检出错,错误原因:{}", e);
                } finally {
                    termBookMetadataMapper.saveBean(termBookMetadata);
                }
            });
        } catch (Exception e) {
            throw new RuntimeException("提交自检任务失败:" + e.toString());

        }
        return "本图书术语正在自检, 请耐心等待";
    }

    @ApiOperation(value = "commit", notes = "新建标准术语接口")
    @PostMapping("commit")
    public boolean commit(@RequestBody TermStandard termStandard) {
        boolean result = false;
        // 中间术语与标准术语对比过程中,不允许新建
        List<TermBookMetadata> termBookMetadatas = termBookMetadataMapper.lambdaQuery().in(TermBookMetadata::getStatus,
                TermBookMetadata.STATUS_COMPARING_STANDARD, TermBookMetadata.STATUS_CONFLICT_STANDARD).list();
        if (termBookMetadatas.size() > 0) {
            throw new RuntimeException("系统中存在正在比对的术语,请稍后再试");
        }
        TermStandard standard = termService.save(termStandard);
        if (standard != null) {
            result = true;
        }
        return result;
    }

    @ApiOperation(value = "selectEditById", notes = "获取原始术语编辑接口")
    @GetMapping("selectEditById")
    public Map<String, Object> selectEditById(String id) {
        Map<String, Object> map = termService.queryEditById(id);
        return map;
    }

    @ApiOperation(value = "deleteById", notes = "删除原始术语接口")
    @GetMapping("deleteById")
    public void deleteById(String id) {
        //  如果有正在比对的标准术语,不允许删除操作
        List<TermBookMetadata> termBookMetadatas = termBookMetadataMapper.selectBeansByWherePart(" status = " + TermBookMetadata.STATUS_COMPARING_STANDARD);
        if (termBookMetadatas.size() > 0) {
            throw new RuntimeException("系统中存在正在比对的术语,请稍后再试");
        }
        termService.deleteById(id);
    }

    private Map outputResult(String code, String message) {
        Map<String, String> map = Maps.newHashMap();
        map.put("result", code);
        map.put("message", message);
        return map;
    }

    @ApiOperation(value = "selectTermHistory", notes = "根据id 查看标准术历史语接口")
    @GetMapping("selectTermHistory")
    public List<TermStandardHistory> selectTermHistory(String id) {

        String sql = "select * from term_standard_history where standard_id = '" + id + "' and term_type=" + Const.WITH_SAME_STANDARD_TERM + " order by id desc";
        List<TermStandardHistory> list = termStandardHistoryMapper.executeMultiSelect(sql);
        return list;
    }

    /**
     * 手动封板的时候获取当前封板信息
     */
    @ApiOperation(value = "selectNewVersionInfo", notes = "手动封板的时候获取当前封板信息")
    @GetMapping("selectNewVersionInfo")
    public Map<String, Object> selectNewVersionInfo() {

        // 标准术语总数
        List<TermStandard> list = termStandardMapper.executeMultiSelect("select * from term_standard where deleted = 0");
        // 新版本的版本号
        List<TermStandardLibHistory> version = termStandardLibHistoryMapper.executeMultiSelect("select * from term_standard_lib_history");
        // 新增条目数
        Map<String, Integer> resultMap = calculateModification(version.size());
        int addition = resultMap.get("addition");
        int modification = resultMap.get("modification");

        Map<String, Object> map = new HashMap<>(1);
        map.put("version", version.size() + 1);
        map.put("total", list.size());
        map.put("addition", addition);
        map.put("modification", modification);
        map.put("date", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE));
        map.put("user", PMPHAppUtil.getCurrentUserCnName());

        Map<String, Object> versionInfoMap = new HashMap<>();
        versionInfoMap.put("versionInfo", map);

        return versionInfoMap;
    }

    private Map<String, Integer> calculateModification(int newVersion) {
        int currentVersion = newVersion - 1;
        Map<String, TermStandardLibHistoryItem> historyMap = getStandardTermOfSpecifiedVersion(currentVersion);
        List<TermStandard> termList = getCurrentStandardTermList();

        int addition = 0;
        int modification = 0;
        for (TermStandard term : termList) {
            if (!historyMap.containsKey(term.getId())) {
                addition++;
            } else {
                TermStandardLibHistoryItem item = historyMap.get(term.getId());
                if (!item.getVersion().equals(term.getVersion())) {
                    modification++;
                }
            }
        }

        Map<String, Integer> map = new HashMap<>(2);
        map.put("addition", addition);
        map.put("modification", modification);
        return map;
    }

    private List<TermStandard> getCurrentStandardTermList() {
        return termStandardMapper.selectBeansByWherePart("deleted = 0");
    }

    @SuppressWarnings("unchecked")
    private Map<String, TermStandardLibHistoryItem> getStandardTermOfSpecifiedVersion(int version) {
        String sql = "select hi.*\n" +
                "from term_standard_lib_history_item hi\n" +
                "         left join term_standard_lib_history h on h.id = hi.vid\n" +
                "where h.version = " + version;
        List<TermStandardLibHistoryItem> itemList = termStandardLibHistoryItemMapper.executeMultiSelect(sql);
        Map<String, TermStandardLibHistoryItem> map = new HashMap<>(itemList.size());
        itemList.forEach(item -> map.put(item.getTid(), item));
        return map;
    }

    /**
     * 封板
     *
     * <p>记录封板信息，并且释放标准术语库上的锁</p>
     */
    @ApiOperation(value = "makeNewVersion", notes = "记录封板信息接口")
    @GetMapping("makeNewVersion")
    public void makeNewVersion(String comments) {
        try {
            // 加锁
            termStandardMapper.executeUpdate("lock tables term_standard read, log write, " +
                    "term_standard_lib_history as h read, term_standard_lib_history_item as hi read, " +
                    "term_standard_lib_history write, term_standard_lib_history_item write");

            // 标准术语总数
            List<TermStandard> list = termStandardMapper.executeMultiSelect("select * from term_standard where deleted = 0");
            // 新版本的版本号
            List<TermStandardLibHistory> version = termStandardLibHistoryMapper.executeMultiSelect("select * from term_standard_lib_history");
            // 新增条目数
            Map<String, Integer> map = calculateModification(version.size());
            int addition = map.get("addition");
            int modification = map.get("modification");

            TermStandardLibHistory history = new TermStandardLibHistory();
            history.setVersion(version.size());
            history.setNumber(list.size());
            history.setAddition(addition);
            history.setModification(modification);
            history.setComments(comments);
            termStandardLibHistoryMapper.saveBean(history);

            List<TermStandard> terms = termStandardMapper.selectBeansByWherePart(" deleted = " + TermStandard.DELETED_NO);
            List<TermStandardLibHistoryItem> itemList = new ArrayList<>();
            for (TermStandard term : terms) {
                TermStandardLibHistoryItem item = new TermStandardLibHistoryItem(term);
                item.setVid(history.getId());
                itemList.add(item);
            }
            itemList.forEach(termStandardLibHistoryItemMapper::saveBean);
        } finally {
            // 解锁
            termStandardMapper.executeUpdate("unlock tables");
        }
    }

    @ApiOperation(value = "downloadTermLib", notes = "下载原始术语接口")
    @GetMapping("downloadTermLib")
    public void downloadTermLib(String id, HttpServletResponse response) throws IOException {
        TermStandardLibHistory history = termStandardLibHistoryMapper.selectById(id);
        XSSFWorkbook workbook = getWorkbook(id);
        response.setContentType("application/xlsx;charset=UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("术语库（" + history.getVersion() + "）.xlsx", "UTF-8"));
        workbook.write(response.getOutputStream());
        response.getOutputStream().close();
    }

    /**
     * 获取术语库Excel对象
     *
     * @param id 术语库版本ID
     * @return Excel对象
     */
    private XSSFWorkbook getWorkbook(String id) {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet();

        XSSFRow row0 = sheet.createRow(0);
        row0.createCell(0).setCellValue("中文正名");
        row0.createCell(1).setCellValue("同义词");
        row0.createCell(2).setCellValue("英文名称");
        row0.createCell(3).setCellValue("英文缩写");
        row0.createCell(4).setCellValue("英文同义词");
        row0.createCell(5).setCellValue("法文名称");
        row0.createCell(6).setCellValue("法文同义词");
        row0.createCell(7).setCellValue("俄文名称");
        row0.createCell(8).setCellValue("俄文同义词");
        row0.createCell(9).setCellValue("德文名称");
        row0.createCell(10).setCellValue("德文同义词");
        row0.createCell(11).setCellValue("日文名称");
        row0.createCell(12).setCellValue("日文同义词");

        String sql = "select * from term_standard_lib_history_item where vid = '" + id + "'";
        List<TermStandardLibHistoryItem> itemList = termStandardLibHistoryItemMapper.executeMultiSelect(sql);
        for (int i = 0; i < itemList.size(); i++) {
            TermStandardLibHistoryItem item = itemList.get(i);
            XSSFRow row = sheet.createRow(i + 1);
            row.createCell(0).setCellValue(item.getName());
            row.createCell(1).setCellValue(item.getSynonym().toJSONString());
            row.createCell(2).setCellValue(item.getEnglishName());
            row.createCell(3).setCellValue(item.getEnglishAbbr());
            row.createCell(4).setCellValue(item.getEnglishNameSynonym());
            row.createCell(5).setCellValue(item.getFrenchName());
            row.createCell(6).setCellValue(item.getFrenchNameSynonym());
            row.createCell(7).setCellValue(item.getRussianName());
            row.createCell(8).setCellValue(item.getRussianNameSynonym());
            row.createCell(9).setCellValue(item.getGermanName());
            row.createCell(10).setCellValue(item.getGermanNameSynonym());
            row.createCell(11).setCellValue(item.getJapaneseName());
            row.createCell(12).setCellValue(item.getJapaneseNameSynonym());
        }
        return workbook;
    }

    /**
     * 原始术语的编辑
     */
    @ApiOperation(value = "termUpdateById", notes = "原始术语的编辑")
    @PostMapping("termUpdateById")
    public void termUpdateById(@RequestBody Term term) {
        List<Term> termList = term.getTermList();
        termList.add(term);
        termService.termUpdateById(termList);
    }

    /**
     * 获取术语库版本历史列表
     */
    @ApiOperation(value = "selectTermLibHistory", notes = "获取术语库版本历史列表")
    @GetMapping("selectTermLibHistory")
    public List<TermStandardLibHistory> selectTermLibHistory() {
        String sql = "select * from term_standard_lib_history order by version desc";
        List<TermStandardLibHistory> list = termStandardLibHistoryMapper.executeMultiSelect(sql);
        return list;
    }

    /**
     * 获取某个版本术语库的所有术语
     */
    @ApiOperation(value = "selectTermsFromLibOfSpecifiedVersion", notes = "获取某个版本术语库的所有术语")
    @GetMapping("selectTermsFromLibOfSpecifiedVersion")
    public List<TermStandardLibHistoryItem> selectTermsFromLibOfSpecifiedVersion(String historyId) {

        String sql = "select * from term_standard_lib_history_item where vid = '" + historyId + "'";
        List<TermStandardLibHistoryItem> list = termStandardLibHistoryItemMapper.executeMultiSelect(sql);
        return list;
    }

    @ApiOperation(value = "selectTermBetweenList", notes = "获取中间术语列表接口")
    @PostMapping("selectTermBetweenList")
    public TermBookMetadata selectTermBetweenList(String termBetween) {
        TermBetween between = JSONObject.toJavaObject(JSON.parseObject(termBetween), TermBetween.class);
        TermBookMetadata termBookMetadata = termService.queryTermBetweenList(between);
        return termBookMetadata;
    }

    @ApiOperation(value = "termBetweenCommit", notes = "编辑中间术语接口")
    @PostMapping("termBetweenCommit")
    public void termBetweenCommit(String id, String name, String englishName, String englishAbbr, String japaneseName, String japaneseNameSynonym,
                                  String frenchName, String frenchNameSynonym, String russianName, String russianNameSynonym, String germanName,
                                  String germanNameSynonym, String synonym, String englishNameSynonym, String englishAbbrSynonym,
                                  String paraphrase) {
        TermBetween termBetween = termBetweenMapper.selectById(id);
        if (StringUtils.isNotBlank(termBetween.getConflictConceptId())) {
            throw new RuntimeException("该条术语与标准术语冲突,请处理完冲突后,再进行编辑");
        }
        termBetween.setName(name);
        termBetween.setEnglishName(StringUtils.join(JSONArray.parseArray(englishName, String.class), ";"));
        termBetween.setEnglishAbbr(StringUtils.join(JSONArray.parseArray(englishAbbr, String.class), ";"));
        termBetween.setJapaneseName(StringUtils.join(JSONArray.parseArray(japaneseName, String.class), ";"));
        termBetween.setJapaneseNameSynonym(StringUtils.join(JSONArray.parseArray(japaneseNameSynonym, String.class), ";"));
        termBetween.setFrenchName(StringUtils.join(JSONArray.parseArray(frenchName, String.class), ";"));
        termBetween.setFrenchNameSynonym(StringUtils.join(JSONArray.parseArray(frenchNameSynonym, String.class), ";"));
        termBetween.setRussianName(StringUtils.join(JSONArray.parseArray(russianName, String.class), ";"));
        termBetween.setRussianNameSynonym(StringUtils.join(JSONArray.parseArray(russianNameSynonym, String.class), ";"));
        termBetween.setGermanName(StringUtils.join(JSONArray.parseArray(germanName, String.class), ";"));
        termBetween.setGermanNameSynonym(StringUtils.join(JSONArray.parseArray(germanNameSynonym, String.class), ";"));
        termBetween.setSynonym(StringUtils.join(JSONArray.parseArray(synonym, String.class), ";"));
        termBetween.setEnglishNameSynonym(StringUtils.join(JSONArray.parseArray(englishNameSynonym, String.class), ";"));
        termBetween.setEnglishAbbrSynonym(StringUtils.join(JSONArray.parseArray(englishAbbrSynonym, String.class), ";"));
        termBetween.setExplanation(JSONArray.parseArray(paraphrase));
        termService.termBetweenSave(termBetween);
    }

    @ApiOperation(value = "selectTermBetweenDetailById", notes = "根据id查看中间术语详情接口")
    @GetMapping("selectTermBetweenDetailById")
    public TermBetween selectTermBetweenDetailById(String id) {
        TermBetween termBetween = termBetweenMapper.selectById(id);
        TermBookMetadata termBookMetadata = termBookMetadataMapper.selectById(termBetween.getTermBookMetadataId());
        // 拼接JSONObject
        JSONObject bookPropertyObject = new JSONObject();
        bookPropertyObject.put("name", termBookMetadata.getName());
        bookPropertyObject.put("version", termBookMetadata.getVersion());
        bookPropertyObject.put("isbn", termBookMetadata.getIsbn());
        bookPropertyObject.put("category", termBookMetadata.getCategory());
        bookPropertyObject.put("type", Const.IMPORT);
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(bookPropertyObject);
        termBetween.setNameSource(jsonArray);
        return termBetween;
    }

    @ApiOperation(value = "selectTermBetweenEditById", notes = "根据id查看中间术语编辑接口")
    @GetMapping("selectTermBetweenEditById")
    public Map<String, Object> selectTermBetweenEditById(String id) {
        Map<String, Object> map = termService.queryTermBetweenEditById(id);
        return map;
    }

    @ApiOperation(value = "deleteTermBetweenById", notes = "根据id删除某条中间术语接口")
    @GetMapping("deleteTermBetweenById")
    public void deleteTermBetweenById(String id) {
        TermBetween termBetween = termBetweenMapper.selectById(id);
        if (StringUtils.isNotBlank(termBetween.getConflictConceptId())) {
            throw new RuntimeException("该条术语与标准术语冲突,请处理完冲突后,再进行删除");
        }
      termService.deleteTermBetweenById(id);
    }

    @ApiOperation(value = "selectBetweenClashList", notes = "查询中间术语冲突页面列表")
    @PostMapping("selectBetweenClashList")
    public TermBookMetadata selectBetweenClashList(String termBetween) {
        TermBetween between = JSONObject.toJavaObject(JSON.parseObject(termBetween), TermBetween.class);
        TermBookMetadata termBookMetadata = termService.queryTermBetweenList(between);
        return termBookMetadata;
    }

    @ApiOperation(value = "solveConflictBookTerm", notes = "校验右侧合并后的数据, 正名是否都有")
    @PostMapping("solveConflictBookTerm")
    public void solveConflictBookTerm(@RequestBody TermBetweenVo termBetweenVo) {
        termService.solveConflictBookTerm(termBetweenVo.getMergedTermList(),
                termBetweenVo.getConflictConceptId(), termBetweenVo.getTermBookMetadataId());
    }

    @ApiOperation(value = "solveConflictStandardTerm", notes = "解决冲突的标准术语接口")
    @PostMapping("solveConflictStandardTerm")
    public void solveConflictStandardTerm(@RequestBody TermStandardVo termStandardVo) {
        termService.solveConflictStandardTerm(termStandardVo);
    }

    @ApiOperation(value = "selectStandardTermByConflictId", notes = "查询当前conflictId冲突的标准术语")
    @GetMapping("selectStandardTermByConflictId")
    public List<TermStandard> selectStandardTermByConflictId(String conflictId) {
        List<TermStandard> termStandards = termStandardMapper.selectBeansByWherePart("conflict_concept_id = '" + conflictId + "'");
        return termStandards;
    }

    @ApiOperation(value = "downloadTerm", notes = "术语下载接口")
    @GetMapping("downloadTerm")
    public void downloadTerm(String id, HttpServletResponse response) throws UnsupportedEncodingException {
        List<Term> terms = termService.lambdaQuery()
                .eq(Term::getTermBookMetadataId, id)
                .eq(Term::getDeleted, 1)
                .eq(Term::getStatus, 4).list();
        // 创建一个Excel文件
        XSSFWorkbook wb = new XSSFWorkbook();
        // 创建第一个工作表
        XSSFSheet sheet = wb.createSheet();
        // 添加表头行
        XSSFRow headRow = sheet.createRow(0);
        // 添加表头内容
        XSSFCell headCell0 = headRow.createCell(0);
        headCell0.setCellValue("术语名称");
        XSSFCell headCell1 = headRow.createCell(1);
        headCell1.setCellValue("术语分类");
        for (int i = 0; i < terms.size(); i++) {
            Term term = terms.get(i);
            XSSFRow cntRow = sheet.createRow(i + 1);
            XSSFCell cntRowCell0 = cntRow.createCell(0);
            cntRowCell0.setCellValue(term.getName());
            XSSFCell cntRowCell1 = cntRow.createCell(1);
            cntRowCell1.setCellValue(term.getXmlClassify());
        }
        response.setContentType("application/xlsx;charset=UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("同组冲突术语.xlsx", "UTF-8"));
        try {
            wb.write(response.getOutputStream());
            response.getOutputStream().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "selectConflictCreateTable", notes = "获取冲突创建数据")
    @GetMapping("selectConflictCreateTable")
    public List<TermStandardHistory> selectConflictCreateTable(String id) {
        // 术语ID
        List<TermStandardHistory> list = termStandardHistoryMapper.lambdaQuery().eq(TermStandardHistory::getStandardId, id).list();
        return list;
    }

    @ApiOperation(value = "selectRelatedBetweenTerm", notes = "查找标准术语的相关术语")
    @PostMapping("selectRelatedBetweenTerm")
    public List<TermBetween> selectRelatedBetweenTerm(@RequestBody List<String> relatedTerm) {
        // 第一个存储的是正名
        // 相关术语排序规则
        // 1）优先显示正名与标准术语正名一致的入库术语
        // 2）在第一排序的基础上按照书本级别优先级进行排序
        // 3）当书本优先级一致时，随机排序即可
        // 返回给前端的相关术语
        // 根据正名查询中间术语, 与标准术语正名相同的术语
        // 返回给前端的术语
        List<TermBetween> relatedBetweenList = Lists.newArrayList();
        Map<String, TermBookMetadata> termBookMetadataMap = termBookMetadataMapper.lambdaQuery().list().stream()
                .collect(Collectors.toMap(TermBookMetadata::getId, Function.identity()));
        // 正名集合
        List<TermBetween> nameList = termBetweenMapper.lambdaQuery().eq(TermBetween::getName, relatedTerm.get(0)).list();
        relatedBetweenList.addAll(sortBetweenList(nameList, termBookMetadataMap));
        // 因为中间术语已经经过自检,同一本书中不可能存在冲突术语
        // 如果根据正名未找到相关术语
        // 暂未考虑超过1000本图书
        List<String> bookIdList = nameList.stream()
                .map(TermBetween::getTermBookMetadataId).collect(Collectors.toList());
        List<TermBetween> synonymList = termBetweenMapper.lambdaQuery()
                .notIn(CollectionUtils.isNotEmpty(bookIdList), TermBetween::getTermBookMetadataId, bookIdList).list();
        if (CollectionUtils.isEmpty(synonymList)) {
            return relatedBetweenList;
        }
        List<TermBetween> tmpSynonymList = Lists.newArrayList();
        synonymList.stream().filter(t -> StringUtils.isNotBlank(t.getSynonym())).forEach(between -> {
            Arrays.stream(between.getSynonym().split(";")).forEach(item -> {
                if (relatedTerm.contains(item)) {
                    tmpSynonymList.add(between);
                }
            });
        });
        // 添加同义词
        relatedBetweenList.addAll(sortBetweenList(tmpSynonymList, termBookMetadataMap));
        return relatedBetweenList;
    }

    private List<TermBetween> sortBetweenList(List<TermBetween> list, Map<String, TermBookMetadata> termBookMetadataMap) {
        if (CollectionUtils.isEmpty(list)) {
            list = Lists.newArrayList();
        }
        list.forEach(t -> {
            TermBookMetadata termBookMetadata = termBookMetadataMap.get(t.getTermBookMetadataId());
            // 拼接JSONObject
            JSONObject bookPropertyObject = new JSONObject();
            bookPropertyObject.put("name", termBookMetadata.getName());
            bookPropertyObject.put("category", termBookMetadata.getCategory());
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(bookPropertyObject);
            t.setNameSource(jsonArray);
            t.setBookCategory(termBookMetadata.getCategory());
        });
        return list.stream().distinct().sorted(Comparator.comparing(TermBetween::getBookCategory)).collect(Collectors.toList());
    }

    @ApiOperation(value = "selectSyncList", notes = "查询推送列表接口")
    @PostMapping("selectSyncList")
    public TermBookMetadata selectSyncList(String term) {
        Term terms = JSONObject.toJavaObject(JSON.parseObject(term), Term.class);
        TermBookMetadata termBookMetadata = termService.querySyncList(terms);
        return termBookMetadata;
    }


    @ApiOperation(value = "syncToPlatform", notes = "术语推送接口")
    @PostMapping("syncToPlatform")
    public void syncToPlatform(@RequestBody Term term) {
        String userName = PMPHAppUtil.getCurrentUserEnName();
        ExecutorServiceFactory.getInstance().submit(() -> {
            termService.syncToPlatform(term, userName, Const.SYNC_OPERATION_ADD);
        });
    }

    @ApiOperation(value = "selectSyncBookMetadata", notes = "查询推送的元数据")
    @PostMapping("selectSyncBookMetadata")
    public Page<TermBookMetadata> selectSyncBookMetadata(@RequestBody TermBookMetadata termBookMetadata) {
        Page<TermBookMetadata> page = termBookMetadataMapper.lambdaQuery()
                .like(StringUtils.isNotBlank(termBookMetadata.getName()), TermBookMetadata::getName, termBookMetadata.getName())
                .eq(Objects.nonNull(termBookMetadata.getCategory()), TermBookMetadata::getCategory, termBookMetadata.getCategory())
                .isNotNull(TermBookMetadata::getCategory)
                .like(StringUtils.isNotBlank(termBookMetadata.getVersion()), TermBookMetadata::getVersion, termBookMetadata.getVersion())
                .like(StringUtils.isNotBlank(termBookMetadata.getIsbn()), TermBookMetadata::getIsbn, termBookMetadata.getIsbn())
                .notIn(TermBookMetadata::getStatus, 0, 4)
                .page(new Page<>(termBookMetadata.getCurrentPage(), termBookMetadata.getPageSize()));
        return page;
    }

    @ApiOperation(value = "syncBookToPlatform", notes = "推送图书结构")
    @PostMapping("syncBookToPlatform")
    public void syncBookToPlatform(@RequestBody TermBookMetadata termBookMetadata) {
        String userName = PMPHAppUtil.getCurrentUserEnName();
        ExecutorServiceFactory.getInstance().submit(() -> {
            termService.syncBookToPlatform(termBookMetadata, userName, Const.SYNC_OPERATION_ADD);
        });
    }
}
